/** 下载文件模块 */
const fs = require("fs"), https = require("https"), readline = require("readline");
const pinfo = require("./pinfo"), pan = require("../pan"), aliPan = require("./aliPan");

let options = {
	hostname: 'pan.baidu.com',
	port: 443,
	path: '/',
	method: 'GET',
	headers: {
		'User-Agent': 'pan.baidu.com'
	}
};

/** 比较目录下载文件 */
function cmp(sp, lp, cb){
	pinfo.listall(sp, (eno, fl)=>{
		if(eno){
			console.log("出错了");
			cb();
		}
		let fids = [];
		for(let f of fl){
			let cf = f.path.replace(sp, '');
			let stat = fs.statSync(lp + cf, {throwIfNoEntry:false});
			if(!stat){
				console.log(f.path, f.size, ">>> null");
				//只下载小文件
				if(DOWNSMALL && f.size > 100 * 1024 * 1024){
					console.log("file is big");
					continue;
				}
				if(f.isdir == 0){
					fids.push(f.fs_id);
				}else{ //如果是目录创建目录
					fs.mkdirSync(lp + cf, {recursive:true});
				}
			}else if(stat.size != f.size){ //大小不等的文件
				console.log("not equal size", f.path, f.size, stat.size);
				if(pan.down_different_size){
					let pos = cf.lastIndexOf('.');
					fs.rename(lp + cf, lp + cf.substr(0,pos) + ".bak" + cf.substr(pos), ()=>{});
					fids.push(f.fs_id);
				}
			}
		}
		if(fids.length){
			downfile(fids, sp, lp, cb);
		}else{
			cb();
		}
	});
}

/** 比较阿里盘下载文件 */
function cmpAli(sp, ap, lp, cb){
	pinfo.listall(sp, async (eno, fl)=>{
		if(eno){
			console.log("出错了");
			cb();
		}
		let fids = [], num = 0;
		console.log("");
		for(let f of fl){
			readline.clearLine(process.stdout, 0);
			readline.cursorTo(process.stdout, 0);
			process.stdout.write("比较文件(" + (++num) + "/" + fl.length + ")");
			//查询本地文件系统
			let cf = f.path.replace(sp, '');
			let stat = fs.statSync(lp + cf, {throwIfNoEntry:false});

			if(f.isdir == 0){ //文件
				let af = f.path.replace(sp, '').replace("/" + f.server_filename, '');
				let files = await aliPan.getPath(ap + af);
				//console.log(f.path);
				//存在文件并且大小相等
				if(files && f.server_filename in files.childs && files.childs[f.server_filename].size == f.size) continue;
				//console.log(files);
				//console.log(f);
				//return;

				if(!stat){
					console.log("");
					console.log(f.path, f.size, ">>> null");
					//只下载小文件
					if(DOWNSMALL && f.size > 100 * 1024 * 1024){
						console.log("file is big");
						continue;
					}
					fids.push(f.fs_id);
				}else if(stat.size != f.size){ //大小不等的文件
					console.log("");
					console.log("not equal size", f.path, f.size, stat.size);
					if(pan.down_different_size){
						let pos = cf.lastIndexOf('.');
						fs.rename(lp + cf, lp + cf.substr(0,pos) + ".bak" + cf.substr(pos), ()=>{});
						fids.push(f.fs_id);
					}
				}
			}else{
				if(!stat) fs.mkdirSync(lp + cf, {recursive:true});
			}
		}
		console.log("");
		//console.log(fids);
		if(fids.length){
			downfile(fids, sp, lp, cb);
		}else{
			cb();
		}
	});
}

/** 下载文件 */
function downfile(fids, bpath, spath, cb){
	let ldfile = [], ldindex = 0;
	getLoadUrl();
	
	let loadfile = function(durl){
		/*if(ldindex >= ldfile.length){
			console.log("下载完成")
			if(fids.length)
				downfile(fids, bpath, spath, cb);
			else
				cb();
			return;
		}*/
		
		//let url = ldfile[ldindex].dlink, size = ldfile[ldindex].size, mm = ldfile[ldindex].path.replace(bpath,''), fn = spath + ldfile[ldindex].path.replace(bpath,'');
		let url = ldfile[0].dlink, size = ldfile[0].size, mm = ldfile[0].path.replace(bpath,''), fn = spath + ldfile[0].path.replace(bpath,'');
		//检查目录
		if(durl){
			url = durl.replace("https://",'').replace("http://",'');
		}else{
			//console.log("["+(ldindex+1)+"/"+ldfile.length+"("+fids.length+")]下载", ldfile[ldindex].path);
			console.log("["+(ldindex+1)+"/"+fids.length+"]下载", new Date().toLocaleString(), ldfile[0].path);
			url = url.replace("https://",'');
		}
		let pos = url.indexOf('/');
		//console.log("file", pos, url.substr(0, pos), url.substr(pos));
		//return;
		let stat = fs.statSync(fn + ".part", {throwIfNoEntry:false});
		let opt = {
			hostname: url.substr(0, pos),
			port: 443,
			path: url.substr(pos) + "&access_token=" + user.access_token,
			method: 'GET',
			headers: {
				'User-Agent': 'pan.baidu.com'
			}
		}
		if(stat && durl){
			opt.headers['Range'] = 'bytes=' + stat.size + "-";
		}
		
		let req = https.request(opt, (res)=>{
			process.stdout.write(` STATUS: ${res.statusCode}`);
			let ret = null, csize = 0, lt = Date.now(), ut = Date.now(), cktt = null, wt = fs.createWriteStream(fn + ".part", {flags:'w+',start:stat?.size||0});//, fd = fs.openSync(fn, 'w+');
			if(opt.headers['Range']) csize = stat.size;
			if(res.statusCode != 200){
				if(res.statusCode == 302){
					//console.log(res.rawHeaders, res.headers, res.rawHeaders.Location)
					loadfile(res.headers.location);
					return;
				}
				if(res.statusCode != 206){ //非部分响应
					ret = Buffer.allocUnsafe(0);
				}
			}
			console.log("");
			res.pipe(wt, {end:false});
			res.on('data', (chunk) => {
				if(ret){
					ret = Buffer.concat([ret, chunk], ret.length + chunk.length);
				}else{
					//fs.appendFileSync(fn, chunk);
					/*fs.write(fd, chunk, (err)=>{
						if(err){
							console.log(err);
							fs.close(fd);
							
							clearTimeout(cktt);
							loadfile();
						}
					});*/ 
					//wt.write(chunk);
				} 
				readline.clearLine(process.stdout, 0);
				readline.cursorTo(process.stdout, 0);
				csize += chunk.length;
				process.stdout.write("[" + csize + "/" + size + "]" + (100*csize/size).toFixed(2) + "% " + (csize / 1024 / ((Date.now() - lt) / 1000)).toFixed(2) + "KB/s");
				ut = Date.now();
			});
			//res.on('close', (e)=>{
			//	console.log("down close", e);
			//});
			res.on('end', () => {
				if(ret) console.log(ret.toString());
				console.log(" 完成");
				clearTimeout(cktt);
				//fs.fsync(fd, ()=>{
				//	fs.close(fd)
				//});
				wt.end();
				fs.rename(fn + ".part", fn, ()=>{});
				ldindex++;
				//loadfile();
				getLoadUrl();
			});
			//检测下载文件是否卡死了
			function ckdown(){
				if(Date.now() - ut > 10*60*1000){ //10分钟下载没有变化重新下载文件
					//fs.unlink(fn, ()=>{});
					console.log("重新下载");
					wt.end(null, ()=>{
						//loadfile();
						getLoadUrl();						
					});
				}else{
					cktt = setTimeout(ckdown, 10*60*1000);
				}
			}
			cktt = setTimeout(ckdown, 10*60*1000);
		});
		req.on("error",(e)=>{
			console.log("下载错误", e);
			fs.unlink(fn, ()=>{}); //删除下载部分的文件
			//继续下载下一个文件
			ldindex++;
			//loadfile();
			getLoadUrl();
		})
		req.end();
	}
	
	function getLoadUrl(){
		if(ldindex >= fids.length){
			cb();
			return;
		}
		options.path = "/rest/2.0/xpan/multimedia?method=filemetas&fsids=[" + fids[ldindex] + "]&dlink=1&access_token=" + user.access_token;
		let req = https.request(options, (res)=>{
			let ret = Buffer.allocUnsafe(0)
			res.on('data', (chunk) => {
				ret = Buffer.concat([ret, chunk], ret.length + chunk.length);
			});
			res.on('end', () => {
				let list = JSON.parse(ret.toString());
				if(list.errno){
					console.log("downlist", ret.toString());
					return cb(list.errno);
				}
				//console.log(list);
				ldfile = list.list;
				loadfile();
			});
		});
		req.end();		
	}
}

exports.cmp = cmp;
exports.cmpAli = cmpAli;